package com.weixing.mall.core.aspect;

import com.weixing.mall.base.exception.OptimisticLockException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;

/**
 * 更新失败，尝试重试切片
 * @author rstyro
 */
@Slf4j
@Aspect
@Configuration
public class OptimisticLockRetryAspect {

    /**
     * 默认重试几次
     */
    private static final int DEFAULT_MAX_RETRIES = 10;

    private int maxRetries = DEFAULT_MAX_RETRIES;
    private int order = 1;

    public void setMaxRetries(int maxRetries) {
        this.maxRetries = maxRetries;
    }

    public int getOrder() {
        return this.order;
    }

    @Pointcut("@annotation(com.weixing.mall.core.annotation.OptimisticLockReTry)")
    public void retryOnOptFailure() {
        // pointcut mark
    }

    @Around("retryOnOptFailure()")
    @Transactional(rollbackFor = Exception.class)
    public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
        int numAttempts = 0;
        do {
            numAttempts++;
            try {
                //再次执行业务代码
                return pjp.proceed();
            } catch (OptimisticLockException ex) {
                if (numAttempts > maxRetries) {
                    //log failure information, and throw exception
//					如果大于 默认的重试机制 次数，我们这回就真正的抛出去了
                    log.info("excute fail after  {} tries", numAttempts);
                    throw new OptimisticLockException("excute fail after " + numAttempts + " tries");
                } else {
                    //如果 没达到最大的重试次数，将再次执行
                    log.info("=====正在重试=====  {} 次", numAttempts);
                }
            }
        } while (numAttempts <= this.maxRetries);

        return null;
    }
}
